package com.blockmeta.bbs.immodule.greendao.repository;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;

import com.blankj.utilcode.util.LogUtils;
import com.blockmeta.bbs.businesslibrary.util.AccountHelper;
import com.blockmeta.bbs.immodule.bean.sort.DateComparator;
import com.blockmeta.bbs.immodule.dao.ChatMessage;
import com.blockmeta.bbs.immodule.dao.TalkListTop;
import com.blockmeta.bbs.immodule.greendao.db.ChatMessageDao;
import com.blockmeta.bbs.immodule.greendao.db.TalkListTopDao;

import org.greenrobot.greendao.query.QueryBuilder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据访问层，主要是对green dao进行包装，以使如果换一个orm或者sqlite数据驱动的时候可以不影响上层业务逻辑。
 * 只包含基本的新增，删除，修改，通用查询的操作
 */
public class ChatMessageRepo implements IChatMessageRepo {

    //消息表存储对象
    private ChatMessageDao chatMessageDao;
    //置顶表存储对象
    private TalkListTopDao talkListTopDao;
    private SQLiteDatabase db;

    public ChatMessageRepo(ChatMessageDao chatMessageDao, TalkListTopDao talkListTopDao
            , SQLiteDatabase imdb) {
        this.chatMessageDao = chatMessageDao;
        this.talkListTopDao = talkListTopDao;
        this.db = imdb;
    }

    /**
     * 添加消息 如果数据不存在 insert 如果数据存在 update
     * 一条消息就是一个记录-------一行ChatMessage
     *
     * @param chatMessage
     * @param whoId
     * @return
     */
    @Override
    public boolean addChatMessage(ChatMessage chatMessage, long whoId) {
        try{
            QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
            // 先查询 通过uuid进行查询  uuid每次都是随机生成的，所以相同消息不再存储！
            qb.where(ChatMessageDao.Properties.Uuid.eq(chatMessage.getUuid())
                    , ChatMessageDao.Properties.WhoId.eq(whoId));
            ChatMessage cm = qb.unique();
            LogUtils.d("author addchatmessage " + chatMessage.toString() + " " + whoId + "isexist" + (cm!= null));
            if (cm != null) {
                LogUtils.d("author addchatmessage cm" + cm.toString());
                cm.setChatMessageId(chatMessage.getChatMessageId());
                chatMessageDao.update(cm);
            } else {
                //多线程下不满足唯一键索引插入的话不会报错，但插入不会重复
                chatMessageDao.insert(chatMessage);
                return true;
            }
        }catch (Exception e){
            LogUtils.d("chatmessage insert duplicate");
        }
        return false;
    }

    @Override
    public List<ChatMessage> getAllChatMessage(long whoId) {
        return chatMessageDao.loadAll();

    }


    /**
     * 删除和某个人或者某个群组的数据！
     */
    @Override
    public void deleteListChatMessage(long whoId, long toId, int type) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(whoId));

        if (type == ChatMessage.MSG_TYPE_UU) {//删除个人聊天
            qb.whereOr(qb.and(ChatMessageDao.Properties.FromId.eq(whoId), ChatMessageDao.Properties.ToId.eq(toId)),
                    qb.and(ChatMessageDao.Properties.FromId.eq(toId), ChatMessageDao.Properties.ToId.eq(whoId)));
            qb.where(ChatMessageDao.Properties.MsgType.eq(ChatMessage.MSG_TYPE_UU));
        } else {//群聊天
            qb.where(ChatMessageDao.Properties.ChatGroupId.eq(toId));
        }
        List<ChatMessage> list = qb.list();
        chatMessageDao.deleteInTx(list);
    }

    /**
     * 获取当前用户下的最大messsageid
     *
     * @param whoId
     * @return
     */
    @Override
    public long getMaxMessageIdByUserId(long whoId) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(whoId));
        qb.limit(1);
        qb.orderDesc(ChatMessageDao.Properties.ChatMessageId);
        ChatMessage m = qb.unique();
        long maxId = 0;
        if (m != null) {
            maxId = m.getChatMessageId();
        }
        return maxId;
    }


    /**
     * 这里面包含了个人聊天以及群聊天！！！
     * @param whoId
     */
    @Override
    public List<ChatMessage> getTalkListMessage(long whoId) {
        // 1.好友消息
        String[] whereArgs = new String[]{whoId + "", whoId + "", whoId + ""};
        String queryString = "SELECT max( " + ChatMessageDao.Properties.Id.columnName
                + " ) FROM  " + ChatMessageDao.TABLENAME + " WHERE "
                + ChatMessageDao.Properties.MsgType.columnName + " = "
                + ChatMessage.MSG_TYPE_UU + " and "
                + ChatMessageDao.Properties.WhoId.columnName + " = ? AND ("
                + ChatMessageDao.Properties.FromId.columnName + "=? OR "
                + ChatMessageDao.Properties.ToId.columnName + "=? )GROUP BY "
                + ChatMessageDao.Properties.FromId.columnName + " , "
                + ChatMessageDao.Properties.ToId.columnName + " ORDER BY "
                + ChatMessageDao.Properties.Date.columnName + " DESC ";
//        LogUtils.v("author", "SQL:" + queryString);

        List<Long> list = new ArrayList<Long>();
        //占位符（？）代替成WhoID
        Cursor cs = this.db.rawQuery(queryString, whereArgs);
        while (cs.moveToNext()) {
            list.add(cs.getLong(0));
        }

        Map<Long, ChatMessage> messages = new HashMap<Long, ChatMessage>();
        //TODO 这里之所以可以去重复，是因为采用HashMap的方式
        if (list.size() > 0) {
            for (Long id : list) {

                ChatMessage m = chatMessageDao.load(id);
                // 获取该用户未读消息条数
                if (m != null) {
                    switch (m.getType()) {
                        case ChatMessage.TYPE_RECEIVE:
                            ChatMessage so = messages.get(m.getFromId());
                            if (so == null
                                    || (so != null && so.getId() < m.getId())) {
                                messages.put(m.getFromId(), m);
                                int count = getUncheckedChatMessageCount(
                                        m.getFromId(), whoId,
                                        ChatMessage.MSG_TYPE_UU);
                                m.setUnCheckedCount(count);
                            }
                            break;
                        case ChatMessage.TYPE_SEND:
                            ChatMessage co = messages.get(m.getToId());
                            if (co == null
                                    || (co != null && co.getId() < m.getId())) {
                                messages.put(m.getToId(), m);
                                int count = getUncheckedChatMessageCount(
                                        m.getToId(), whoId, ChatMessage.MSG_TYPE_UU);
                                m.setUnCheckedCount(count);
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        // 2.群聊天记录
        String[] whereArgs2 = new String[]{whoId + ""};
        String queryString2 = "SELECT max( " + ChatMessageDao.Properties.Id.columnName
                + " ) FROM  " + ChatMessageDao.TABLENAME + " WHERE "
                + ChatMessageDao.Properties.MsgType.columnName + " = "
                + ChatMessage.MSG_TYPE_UCG + " and "
                + ChatMessageDao.Properties.WhoId.columnName + " = ?  GROUP BY "
                + ChatMessageDao.Properties.ChatGroupId.columnName + " ORDER BY "
                + ChatMessageDao.Properties.Date.columnName + " DESC ";
//        LogUtils.v("author", "SQL2:" + queryString2);

        List<Long> list2 = new ArrayList<Long>();
        Cursor cs2 = this.db.rawQuery(queryString2, whereArgs2);
        while (cs2.moveToNext()) {
            list2.add(cs2.getLong(0));
        }
        if (list2 != null && list2.size() > 0) {
            for (long id : list2) {
                ChatMessage m = chatMessageDao.load(id);
                if (m != null) {
                    messages.put(m.getChatGroupId() + 5000000, m);// 防止id重叠
                    //TODO  设置群消息未读消息
                    int count = getUncheckedGroupMessageCount(m.getChatGroupId(), whoId);
                    m.setUnCheckedCount(count);
                }
            }
        }
        // 4.添加
        List<ChatMessage> l = new ArrayList<ChatMessage>();
        if (messages.size() > 0) {
            l.addAll(messages.values());
        }
        //最新消息需要按照时间排序
        Collections.sort(l, new DateComparator());
        List<ChatMessage> messageList = new ArrayList<>();
        for (int i = 0; i < l.size(); i++) {
            ChatMessage message = l.get(i);
            if (isStickMessage(message)) {
                messageList.add(l.remove(i));
                i--;
            }
        }
        messageList.addAll(l);
//        Collections.sort(l, new StickComparator());
        return messageList;
    }

    @Override
    public boolean isStickMessage(ChatMessage cm) {
        int type = cm.getMsgType();
        long fromId = getFromId(cm);
        int uidInt = AccountHelper.getUidInt();

        QueryBuilder<TalkListTop> talkListQb = talkListTopDao.queryBuilder();
        talkListQb.where(TalkListTopDao.Properties.FromId.eq(fromId)
                , TalkListTopDao.Properties.Type.eq(type), TalkListTopDao.Properties.WhoId.eq(uidInt));
        long count = talkListQb.count();
        return count > 0;
    }

    @Override
    public ChatMessage getChatMessageByUUid(String uuid, long whoId) {
        QueryBuilder<ChatMessage> chatMessageQueryBuilder = chatMessageDao.queryBuilder();
        ChatMessage unique = chatMessageQueryBuilder.where(ChatMessageDao.Properties.Uuid.eq(uuid)
                , ChatMessageDao.Properties.WhoId.eq(whoId)).unique();
        return unique;
    }

    @Override
    public boolean updateChatMessage(ChatMessage chatMessage) {
        chatMessageDao.update(chatMessage);
        return true;
    }

    @Override
    public void deleteChatMessageByUuid(String uuid, long whoId) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.Uuid.eq(uuid)
                , ChatMessageDao.Properties.WhoId.eq(whoId));
        ChatMessage msg = qb.unique();
        if (msg != null) {
            chatMessageDao.delete(msg);
        }
    }

    @Override
    public List<ChatMessage> searchChatMessagePaged(String word, int pageSize, int page, String orderField, String orderType) {

        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(AccountHelper.getUidInt()),
                ChatMessageDao.Properties.Content.like("%" + word + "%"));
        if (TextUtils.isEmpty(orderField)) {
            qb.orderDesc(ChatMessageDao.Properties.Date);
        }
        qb.offset(page * pageSize).limit(pageSize);
        return qb.list();
    }


    @Override
    public List<ChatMessage> getChatMessageList(long whoId, long fromId, int chatType, int fetchSize, long ltMessageId, long gtMessageId) {
        QueryBuilder<ChatMessage> qb = getTalkToMessageQuery(whoId, fromId, chatType);

        List<ChatMessage> list;
        if (ltMessageId != 0 && gtMessageId != 0) {
            qb.where(ChatMessageDao.Properties.Id.lt(ltMessageId),
                    ChatMessageDao.Properties.Id.gt(gtMessageId));
            qb.orderDesc(ChatMessageDao.Properties.Id);
            qb.limit(fetchSize);
            list = qb.list();
            //数据结果需要为id正序
            Collections.reverse(list);
        } else if (ltMessageId != 0) {
            //获取比ltmsgid小连续的n条,用于获取历史消息
            qb.where(ChatMessageDao.Properties.Id.lt(ltMessageId));
            qb.orderDesc(ChatMessageDao.Properties.Id);
            qb.limit(fetchSize);
            list = qb.list();
            //数据结果需要为id正序
            Collections.reverse(list);
        } else if (gtMessageId != 0) {
            //获取比gtmsgid大的连续的n条,用于获取后面发来的消息
            qb.where(ChatMessageDao.Properties.Id.gt(gtMessageId));
            qb.orderAsc(ChatMessageDao.Properties.Id);
            qb.limit(fetchSize);
            list = qb.list();
        } else {
            qb.orderDesc(ChatMessageDao.Properties.Id);
            qb.limit(fetchSize);
            list = qb.list();
            //数据结果需要为id正序
            Collections.reverse(list);
        }

        return list;
    }

    @Override
    public List<ChatMessage> getLocChatMessageList(long whoId, long fromId, int chatType, int pageSize, long locMessageId) {
        QueryBuilder<ChatMessage> qb = getTalkToMessageQuery(whoId, fromId, chatType);

        List<ChatMessage> list;
        //获取比ltmsgid小连续的n条,用于获取历史消息
        qb.where(ChatMessageDao.Properties.Id.le(locMessageId));
        qb.orderDesc(ChatMessageDao.Properties.Id);
        qb.limit(pageSize);
        list = qb.list();
        //数据结果需要为id正序
        Collections.reverse(list);

        return list;
    }

    @Override
    public List<ChatMessage> getGroupTalkListMessage(int whoId) {
        Map<Long, ChatMessage> messages = new HashMap<Long, ChatMessage>();
        // 2.群聊天记录
        String[] whereArgs2 = new String[]{whoId + ""};
        String queryString2 = "SELECT max( " + ChatMessageDao.Properties.Id.columnName
                + " ) FROM  " + ChatMessageDao.TABLENAME + " WHERE "
                + ChatMessageDao.Properties.MsgType.columnName + " = "
                + ChatMessage.MSG_TYPE_UCG + " and "
                + ChatMessageDao.Properties.WhoId.columnName + " = ?  GROUP BY "
                + ChatMessageDao.Properties.ChatGroupId.columnName + " ORDER BY "
                + ChatMessageDao.Properties.Date.columnName + " DESC ";
//        LogUtils.v("author", "SQL2:" + queryString2);

        List<Long> list2 = new ArrayList<Long>();
        Cursor cs2 = this.db.rawQuery(queryString2, whereArgs2);
        while (cs2.moveToNext()) {
            list2.add(cs2.getLong(0));
        }
        if (list2 != null && list2.size() > 0) {
            for (long id : list2) {
                ChatMessage m = chatMessageDao.load(id);
                if (m != null) {
                    messages.put(m.getChatGroupId() + 5000000, m);// 防止id重叠
                    //TODO  设置群消息未读消息
                    int count = getUncheckedGroupMessageCount(m.getChatGroupId(), whoId);
                    m.setUnCheckedCount(count);
                }
            }
        }
        // 4.添加
        List<ChatMessage> l = new ArrayList<ChatMessage>();
        if (messages.size() > 0) {
            l.addAll(messages.values());
        }
        //最新消息需要按照时间排序
        Collections.sort(l, new DateComparator());
        List<ChatMessage> messageList = new ArrayList<>();
        for (int i = 0; i < l.size(); i++) {
            ChatMessage message = l.get(i);
            if (isStickMessage(message)) {
                messageList.add(l.remove(i));
                i--;
            }
        }
        messageList.addAll(l);
//        Collections.sort(l, new StickComparator());
        return messageList;
    }

    @Override
    public List<ChatMessage> getPersonalTalkListMessage(int whoId) {
        // 1.好友消息
        String[] whereArgs = new String[]{whoId + "", whoId + "", whoId + ""};
        String queryString = "SELECT max( " + ChatMessageDao.Properties.Id.columnName
                + " ) FROM  " + ChatMessageDao.TABLENAME + " WHERE "
                + ChatMessageDao.Properties.MsgType.columnName + " = "
                + ChatMessage.MSG_TYPE_UU + " and "
                + ChatMessageDao.Properties.WhoId.columnName + " = ? AND ("
                + ChatMessageDao.Properties.FromId.columnName + "=? OR "
                + ChatMessageDao.Properties.ToId.columnName + "=? )GROUP BY "
                + ChatMessageDao.Properties.FromId.columnName + " , "
                + ChatMessageDao.Properties.ToId.columnName + " ORDER BY "
                + ChatMessageDao.Properties.Date.columnName + " DESC ";
//        LogUtils.v("author", "SQL:" + queryString);

        List<Long> list = new ArrayList<Long>();
        //占位符（？）代替成WhoID
        Cursor cs = this.db.rawQuery(queryString, whereArgs);
        while (cs.moveToNext()) {
            list.add(cs.getLong(0));
        }

        Map<Long, ChatMessage> messages = new HashMap<Long, ChatMessage>();
        //TODO 这里之所以可以去重复，是因为采用HashMap的方式
        if (list.size() > 0) {
            for (Long id : list) {

                ChatMessage m = chatMessageDao.load(id);
                // 获取该用户未读消息条数
                if (m != null) {
                    switch (m.getType()) {
                        case ChatMessage.TYPE_RECEIVE:
                            ChatMessage so = messages.get(m.getFromId());
                            if (so == null
                                    || (so != null && so.getId() < m.getId())) {
                                messages.put(m.getFromId(), m);
                                int count = getUncheckedChatMessageCount(
                                        m.getFromId(), whoId,
                                        ChatMessage.MSG_TYPE_UU);
                                m.setUnCheckedCount(count);
                            }
                            break;
                        case ChatMessage.TYPE_SEND:
                            ChatMessage co = messages.get(m.getToId());
                            if (co == null
                                    || (co != null && co.getId() < m.getId())) {
                                messages.put(m.getToId(), m);
                                int count = getUncheckedChatMessageCount(
                                        m.getToId(), whoId, ChatMessage.MSG_TYPE_UU);
                                m.setUnCheckedCount(count);
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        // 4.添加
        List<ChatMessage> l = new ArrayList<ChatMessage>();
        if (messages.size() > 0) {
            l.addAll(messages.values());
        }
        //最新消息需要按照时间排序
        Collections.sort(l, new DateComparator());
        List<ChatMessage> messageList = new ArrayList<>();
        for (int i = 0; i < l.size(); i++) {
            ChatMessage message = l.get(i);
            if (isStickMessage(message)) {
                messageList.add(l.remove(i));
                i--;
            }
        }
        messageList.addAll(l);
//        Collections.sort(l, new StickComparator());
        return messageList;
    }

    @Override
    public int getUncheckedUUMessageCount(long uidInt) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(uidInt)
                , ChatMessageDao.Properties.Checked.eq(false)
                , ChatMessageDao.Properties.MsgType.eq(ChatMessage.MSG_TYPE_UU)
                );
        int unCheckedCount = (int) qb.count();
        return unCheckedCount;

    }

    @Override
    public int getUncheckedUCGMessageCountExceptNoDisturb(long uidInt, List<Long> noDisturbGroupIds) {

        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(uidInt)
                , ChatMessageDao.Properties.Checked.eq(false)
                , ChatMessageDao.Properties.MsgType.eq(ChatMessage.MSG_TYPE_UCG)
                , ChatMessageDao.Properties.ChatGroupId.notIn(noDisturbGroupIds));
        int unCheckedCount = (int) qb.count();
        return unCheckedCount;

    }

    private long getFromId(ChatMessage cm) {
        long fromId = 0;
        if (cm.getMsgType() == ChatMessage.MSG_TYPE_UCG) {
            fromId = cm.getChatGroupId();
        } else if (cm.getMsgType() == ChatMessage.MSG_TYPE_UU) {
            fromId = cm.getType() == ChatMessage.TYPE_SEND ? cm.getToId() : cm.getFromId();
        }
        return fromId;
    }


    @Override
    public int getUncheckedChatMessageCount(long fromId, long whoId, int msgType) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.FromId.eq(fromId), ChatMessageDao.Properties.WhoId.eq(whoId),
                ChatMessageDao.Properties.Checked.eq(false), ChatMessageDao.Properties.MsgType.eq(msgType));
        List l = qb.list();
        int count = 0;
        if (l != null) {
            count = l.size();
        }
        return count;
    }


    @Override
    public int getUncheckedGroupMessageCount(long groupId, long whoId) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.ChatGroupId.eq(groupId), ChatMessageDao.Properties.WhoId.eq(whoId),
                ChatMessageDao.Properties.Checked.eq(false), ChatMessageDao.Properties.MsgType.eq(ChatMessage.MSG_TYPE_UCG));
        List l = qb.list();
        int count = 0;
        if (l != null) {
            count = l.size();
        }
        return count;
    }


    /**
     * 设置和某个聊天为已读
     *  @param whoId
     * @param friendId
     */
    @Override
    public void updateChatMessageChecked(long whoId, long friendId) {
//        ContentValues cv = new ContentValues();
//        cv.put(ChatMessageDao.Properties.Checked.columnName, true);
//
//        String[] args = {whoId + "", friendId + ""};
//        db.update(ChatMessageDao.TABLENAME, cv, ChatMessageDao.Properties.WhoId.columnName
//                + " =? and " + ChatMessageDao.Properties.MsgType.columnName  + "= 0 and " + ChatMessageDao.Properties.FromId.columnName + " =? ", args);
        LogUtils.d("tingim", "updateChatMessageChecked");
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(whoId), ChatMessageDao.Properties.MsgType.eq(0)
                , ChatMessageDao.Properties.Checked.eq(false), ChatMessageDao.Properties.FromId.eq(friendId));
        List<ChatMessage> list = qb.list();
        for (ChatMessage message : list) {
            message.setChecked(true);
        }
        chatMessageDao.updateInTx(list);
    }

    /**
     * 设置群消息为已读
     *  @param whoId
     * @param groupId
     */
    @Override
    public void updateGroupMessageCheck(long whoId, long groupId) {
//        ContentValues cv = new ContentValues();
//        cv.put(ChatMessageDao.Properties.Checked.columnName, true);
//        String[] args = {whoId + "", groupId + ""};
//        db.update(ChatMessageDao.TABLENAME, cv, ChatMessageDao.Properties.WhoId.columnName
//                + " =? and " + ChatMessageDao.Properties.ChatGroupId.columnName + " =? ", args);

        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(whoId), ChatMessageDao.Properties.ChatGroupId.eq(groupId)
                , ChatMessageDao.Properties.Checked.eq(false));
        List<ChatMessage> list = qb.list();
        for (ChatMessage message : list) {
            message.setChecked(true);
        }
        chatMessageDao.updateInTx(list);


    }


    /**
     * 根据聊天对象删除这一类的聊天消息
     *
     * @param id
     */
    @Override
    public void deleteChatMessageById(Long id) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.Id.eq(id));
        ChatMessage msg = qb.unique();
        if (msg != null) {
            chatMessageDao.delete(msg);
        }

    }


    /**
     * 根据消息id查找所有相关消息进行置顶
     *
     * @param id
     * @param openOrDown
     */
    @Override
    public void updateChatMessageStick(Long id, boolean openOrDown) {

        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.Id.eq(id));
        ChatMessage cm = qb.unique();
        if (cm != null) {

            TalkListTop top = new TalkListTop();
            int type = cm.getMsgType();
            long fromId = getFromId(cm);
            top.setFromId(fromId);
            top.setType(type);
            int uidInt = AccountHelper.getUidInt();
            top.setWhoId(Long.valueOf(uidInt));

            QueryBuilder<TalkListTop> talkListQb = talkListTopDao.queryBuilder();
            talkListQb.where(TalkListTopDao.Properties.FromId.eq(fromId)
                    , TalkListTopDao.Properties.Type.eq(type), TalkListTopDao.Properties.WhoId.eq(uidInt));
            long count = talkListQb.count();
            if (count == 0 && openOrDown) {
                talkListTopDao.insert(top);
            } else if (count > 0 && !openOrDown) {
                talkListTopDao.delete(talkListQb.unique());
            }

        }
    }

    /**
     * 获得圈子或者人的置顶属性
     *
     * @param id
     * @param type
     * @return
     */
    @Override
    public boolean getCircleStick(long id, Integer type) {
        QueryBuilder<TalkListTop> qbGroup = talkListTopDao.queryBuilder();
        qbGroup.where(TalkListTopDao.Properties.FromId.eq(id)
                , TalkListTopDao.Properties.Type.eq(ChatMessage.MSG_TYPE_UCG)
                , TalkListTopDao.Properties.WhoId.eq(AccountHelper.getUid()));
        return qbGroup.count() > 0;
    }

    @Override
    public void updateCircleStick(Long circleId, boolean openOrDown) {

        TalkListTop top = new TalkListTop();
        int type = ChatMessage.MSG_TYPE_UCG;
        Long fromId = circleId;
        top.setFromId(fromId);
        top.setType(type);
        int uidInt = AccountHelper.getUidInt();
        top.setWhoId(Long.valueOf(uidInt));

        QueryBuilder<TalkListTop> talkListQb = talkListTopDao.queryBuilder();
        List<TalkListTop> list = talkListQb.where(TalkListTopDao.Properties.FromId.eq(fromId)
                , TalkListTopDao.Properties.Type.eq(type), TalkListTopDao.Properties.WhoId.eq(uidInt)).list();
        long count = list.size();
        if (count == 0 && openOrDown) {
            talkListTopDao.insert(top);
        } else if (count > 0 && !openOrDown) {
            talkListTopDao.deleteInTx(list);
        } else {
            //不用操作

        }
    }

    @Override
    public void updateChatMessageReaded(Long id, boolean readOrUnread) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.Id.eq(id));
        ChatMessage cm = qb.unique();
        if (cm != null) {

            if (cm.getMsgType() == ChatMessage.MSG_TYPE_UU) {
                long friendId = 0;
                if (cm.getType() == ChatMessage.TYPE_SEND) {
                    friendId = cm.getToId();
                } else if (cm.getType() == ChatMessage.TYPE_RECEIVE) {
                    friendId = cm.getFromId();
                }
                updateChatMessageChecked(cm.getWhoId(), friendId);
            } else if (cm.getMsgType() == ChatMessage.MSG_TYPE_UCG) {
                updateGroupMessageCheck(cm.getWhoId(), cm.getChatGroupId());
            }
        }
    }


    private QueryBuilder<ChatMessage> getTalkToMessageQuery(long whoId, long toUserId, int type) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();

        switch (type) {
            case ChatMessage.MSG_TYPE_UU://好友会话
                qb.where(ChatMessageDao.Properties.WhoId.eq(whoId), ChatMessageDao.Properties.MsgType
                        .eq(ChatMessage.MSG_TYPE_UU), qb.or(qb.and(
                        ChatMessageDao.Properties.FromId.eq(toUserId),
                        ChatMessageDao.Properties.Type.eq(ChatMessage.TYPE_RECEIVE),
                        ChatMessageDao.Properties.ToId.eq(whoId)), qb.and(
                        ChatMessageDao.Properties.FromId.eq(whoId),
                        ChatMessageDao.Properties.Type.eq(ChatMessage.TYPE_SEND),
                        ChatMessageDao.Properties.ToId.eq(toUserId))));
                break;
            case ChatMessage.MSG_TYPE_UCG://群消息
                qb.where(ChatMessageDao.Properties.WhoId.eq(whoId),
                        ChatMessageDao.Properties.ChatGroupId.eq(toUserId),
                        ChatMessageDao.Properties.MsgType.eq(ChatMessage.MSG_TYPE_UCG));
                break;
        }
        return qb;
    }

    @Override
    public long getUnReadCount(long whoId, long toUserId, int type) {
        QueryBuilder<ChatMessage> qb = getTalkToMessageQuery(whoId, toUserId, type);
        qb.where(ChatMessageDao.Properties.Checked.eq(false));
        long count = qb.count();
        return count;
    }

    @Override
    public int getUncheckedMessageCountExceptNoDisturb(long uidInt, List<Long> noDisturbGroupIds) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(uidInt)
                , ChatMessageDao.Properties.Checked.eq(false)
                , ChatMessageDao.Properties.ChatGroupId.notIn(noDisturbGroupIds));
        int unCheckedCount = (int) qb.count();
        return unCheckedCount;
    }

    @Override
    public int getTalkListMessageSize(long whoId) {
        // 1.好友消息
        String[] whereArgs = new String[]{whoId + "", whoId + "", whoId + ""};
        String queryString = "SELECT max( " + ChatMessageDao.Properties.Id.columnName
                + " ) FROM  " + ChatMessageDao.TABLENAME + " WHERE "
                + ChatMessageDao.Properties.MsgType.columnName + " = "
                + ChatMessage.MSG_TYPE_UU + " and "
                + ChatMessageDao.Properties.WhoId.columnName + " = ? AND ("
                + ChatMessageDao.Properties.FromId.columnName + "=? OR "
                + ChatMessageDao.Properties.ToId.columnName + "=? )GROUP BY "
                + ChatMessageDao.Properties.FromId.columnName + " , "
                + ChatMessageDao.Properties.ToId.columnName + " ORDER BY "
                + ChatMessageDao.Properties.Date.columnName + " DESC ";

        List<Long> list = new ArrayList<Long>();
        //占位符（？）代替成WhoID
        Cursor cs = this.db.rawQuery(queryString, whereArgs);
        while (cs.moveToNext()) {
            list.add(cs.getLong(0));
        }

        Map<Long, ChatMessage> messages = new HashMap<Long, ChatMessage>();
        if (list.size() > 0) {
            for (Long id : list) {

                ChatMessage m = chatMessageDao.load(id);
                // 获取该用户未读消息条数
                if (m != null) {
                    switch (m.getType()) {
                        case ChatMessage.TYPE_RECEIVE:
                            ChatMessage so = messages.get(m.getFromId());
                            if (so == null
                                    || (so != null && so.getId() < m.getId())) {
                                messages.put(m.getFromId(), m);
                            }
                            break;
                        case ChatMessage.TYPE_SEND:
                            ChatMessage co = messages.get(m.getToId());
                            if (co == null
                                    || (co != null && co.getId() < m.getId())) {
                                messages.put(m.getToId(), m);
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        // 2.群聊天记录
        String[] whereArgs2 = new String[]{whoId + ""};
        String queryString2 = "SELECT max( " + ChatMessageDao.Properties.Id.columnName
                + " ) FROM  " + ChatMessageDao.TABLENAME + " WHERE "
                + ChatMessageDao.Properties.MsgType.columnName + " = "
                + ChatMessage.MSG_TYPE_UCG + " and "
                + ChatMessageDao.Properties.WhoId.columnName + " = ?  GROUP BY "
                + ChatMessageDao.Properties.ChatGroupId.columnName + " ORDER BY "
                + ChatMessageDao.Properties.Date.columnName + " DESC ";
//        LogUtils.v("author", "SQL2:" + queryString2);

        List<Long> list2 = new ArrayList<Long>();
        Cursor cs2 = this.db.rawQuery(queryString2, whereArgs2);
        while (cs2.moveToNext()) {
            list2.add(cs2.getLong(0));
        }
        if (list2 != null && list2.size() > 0) {
            for (long id : list2) {
                ChatMessage m = chatMessageDao.load(id);
                if (m != null) {
                    messages.put(m.getChatGroupId() + 5000000, m);// 防止id重叠
                }
            }
        }
        // 4.添加
        List<ChatMessage> l = new ArrayList<ChatMessage>();
        if (messages.size() > 0) {
            l.addAll(messages.values());
        }
        return l.size();
    }

    @Override
    public void updateMessageStatusToFail(long uidInt) {
        QueryBuilder<ChatMessage> qb = chatMessageDao.queryBuilder();
        qb.where(ChatMessageDao.Properties.WhoId.eq(uidInt)
                , ChatMessageDao.Properties.Status.eq(ChatMessage.STATUS_SENDING)
        );
        List<ChatMessage> chatMessages = qb.list();
        for (ChatMessage message : chatMessages) {
            message.setStatus(ChatMessage.STATUS_FAIL_TIMEOUT);
        }
        chatMessageDao.updateInTx(chatMessages);
    }
}
